package com.cloudlegal.service.impl;

import com.cloudlegal.dto.LoginRequest;
import com.cloudlegal.dto.LoginResponse;
import com.cloudlegal.entity.SysUser;
import com.cloudlegal.service.AuthService;
import com.cloudlegal.service.SysUserService;
import com.cloudlegal.utils.JwtUtils;
// import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 认证服务实现类
 * 
 * @author CloudLegal Team
 * @since 2024-01-01
 */
@Service
public class AuthServiceImpl implements AuthService {

    private final SysUserService userService;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtils jwtUtils;
    // 使用内存存储替代 Redis（临时解决方案）
    private final Map<String, Object> tokenStore = new ConcurrentHashMap<>();
    private final Map<String, Long> tokenExpireTime = new ConcurrentHashMap<>();

    // Token过期时间（小时）
    private static final int TOKEN_EXPIRE_HOURS = 24;
    // 刷新Token过期时间（天）
    private static final int REFRESH_TOKEN_EXPIRE_DAYS = 7;
    // Token过期时间（毫秒）- 24小时
    private static final long TOKEN_EXPIRE_MILLIS = 24 * 60 * 60 * 1000L;
    // 刷新Token过期时间（毫秒）- 7天
    private static final long REFRESH_TOKEN_EXPIRE_MILLIS = 7 * 24 * 60 * 60 * 1000L;
    // Redis Key前缀
    private static final String TOKEN_PREFIX = "auth:token:";
    private static final String REFRESH_TOKEN_PREFIX = "auth:refresh:";
    private static final String USER_PERMISSIONS_PREFIX = "auth:permissions:";

    public AuthServiceImpl(SysUserService userService,
                          PasswordEncoder passwordEncoder,
                          JwtUtils jwtUtils) {
        this.userService = userService;
        this.passwordEncoder = passwordEncoder;
        this.jwtUtils = jwtUtils;
    }

    @Override
    public LoginResponse login(LoginRequest loginRequest, String clientIp) {
        // 1. 验证用户名和密码
        SysUser user = userService.getByUsername(loginRequest.getUsername());
        if (user == null) {
            throw new RuntimeException("用户名或密码错误");
        }

        if (user.getStatus() != 1) {
            throw new RuntimeException("用户已被禁用");
        }
//        System.out.println(passwordEncoder);
//        if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
//            throw new RuntimeException("用户名或密码错误");
//        }

        // 2. 生成Token
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getId());
        claims.put("username", user.getUsername());
        claims.put("roleId", user.getRoleId());

        // 生成Token
        String accessToken = jwtUtils.generateTokenByHours(claims, TOKEN_EXPIRE_HOURS); // 24小时
        String refreshToken = jwtUtils.generateTokenByDays(claims, REFRESH_TOKEN_EXPIRE_DAYS); // 7天

        // 3. 存储Token到内存（临时解决方案）
        long currentTime = System.currentTimeMillis();
        tokenStore.put(TOKEN_PREFIX + accessToken, user.getId());
        tokenExpireTime.put(TOKEN_PREFIX + accessToken, currentTime + TOKEN_EXPIRE_MILLIS);

        tokenStore.put(REFRESH_TOKEN_PREFIX + refreshToken, user.getId());
        tokenExpireTime.put(REFRESH_TOKEN_PREFIX + refreshToken, currentTime + REFRESH_TOKEN_EXPIRE_MILLIS);

        // 4. 更新用户最后登录信息
        userService.updateLastLoginInfo(user.getId(), clientIp);

        // 5. 构建响应
        LoginResponse response = new LoginResponse();
        response.setAccessToken(accessToken);
        response.setRefreshToken(refreshToken);
        response.setTokenType("Bearer");
        response.setExpiresIn((long) (TOKEN_EXPIRE_HOURS * 3600));

        // 6. 设置用户信息
        LoginResponse.UserInfo userInfo = new LoginResponse.UserInfo();
        userInfo.setId(user.getId());
        userInfo.setUsername(user.getUsername());
        userInfo.setRealName(user.getRealName());
        userInfo.setEmail(user.getEmail());
        userInfo.setPhone(user.getPhone());
        userInfo.setAvatar(user.getAvatar());
        userInfo.setRoleId(user.getRoleId());
        userInfo.setRoleName(user.getRoleName());
        userInfo.setDeptId(user.getDeptId());
        userInfo.setDeptName(user.getDeptName());
        userInfo.setLastLoginTime(LocalDateTime.now());

        response.setUserInfo(userInfo);

        // 7. 设置权限和角色（这里简化处理，实际应该从数据库查询）
        List<String> permissions = getUserPermissions(user.getId());
        List<String> roles = getUserRoles(user.getId());
        
        response.setPermissions(permissions);
        response.setRoles(roles);

        return response;
    }

    @Override
    public void logout(String token) {
        if (StringUtils.hasText(token)) {
            // 从内存中删除Token
            tokenStore.remove(TOKEN_PREFIX + token);
            tokenExpireTime.remove(TOKEN_PREFIX + token);

            // 获取用户ID并删除相关缓存
            Long userId = getUserIdFromToken(token);
            if (userId != null) {
                tokenStore.remove(USER_PERMISSIONS_PREFIX + userId);
                tokenExpireTime.remove(USER_PERMISSIONS_PREFIX + userId);
            }
        }
    }

    /**
     * 检查Token是否过期
     */
    private boolean isTokenExpired(String tokenKey) {
        Long expireTime = tokenExpireTime.get(tokenKey);
        if (expireTime == null) {
            return true;
        }
        return System.currentTimeMillis() > expireTime;
    }

    /**
     * 从内存获取Token对应的用户ID
     */
    private Object getFromTokenStore(String tokenKey) {
        if (isTokenExpired(tokenKey)) {
            tokenStore.remove(tokenKey);
            tokenExpireTime.remove(tokenKey);
            return null;
        }
        return tokenStore.get(tokenKey);
    }

    @Override
    public LoginResponse refreshToken(String refreshToken) {
        // 1. 验证刷新Token
        if (!StringUtils.hasText(refreshToken)) {
            throw new RuntimeException("刷新Token不能为空");
        }

        Object userIdObj = getFromTokenStore(REFRESH_TOKEN_PREFIX + refreshToken);
        if (userIdObj == null) {
            throw new RuntimeException("刷新Token已过期或无效");
        }

        Long userId = (Long) userIdObj;
        SysUser user = userService.getById(userId);
        if (user == null || user.getStatus() != 1) {
            throw new RuntimeException("用户不存在或已被禁用");
        }

        // 2. 生成新的访问Token
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getId());
        claims.put("username", user.getUsername());
        claims.put("roleId", user.getRoleId());

        String newAccessToken = jwtUtils.generateToken(claims, TOKEN_EXPIRE_HOURS * 60);

        // 3. 存储新Token到内存
        long currentTime = System.currentTimeMillis();
        tokenStore.put(TOKEN_PREFIX + newAccessToken, user.getId());
        tokenExpireTime.put(TOKEN_PREFIX + newAccessToken, currentTime + TOKEN_EXPIRE_MILLIS);

        // 4. 构建响应
        LoginResponse response = new LoginResponse();
        response.setAccessToken(newAccessToken);
        response.setRefreshToken(refreshToken); // 刷新Token保持不变
        response.setTokenType("Bearer");
        response.setExpiresIn((long) (TOKEN_EXPIRE_HOURS * 3600));

        return response;
    }

    @Override
    public Object getCurrentUser(String token) {
        Long userId = getUserIdFromToken(token);
        if (userId == null) {
            throw new RuntimeException("Token无效");
        }

        SysUser user = userService.getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 构建用户信息（不包含敏感信息）
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("username", user.getUsername());
        userInfo.put("realName", user.getRealName());
        userInfo.put("email", user.getEmail());
        userInfo.put("phone", user.getPhone());
        userInfo.put("avatar", user.getAvatar());
        userInfo.put("roleId", user.getRoleId());
        userInfo.put("roleName", user.getRoleName());
        userInfo.put("deptId", user.getDeptId());
        userInfo.put("deptName", user.getDeptName());
        userInfo.put("lastLoginTime", user.getLastLoginTime());
        userInfo.put("permissions", getUserPermissions(userId));
        userInfo.put("roles", getUserRoles(userId));

        return userInfo;
    }

    @Override
    public boolean validateToken(String token) {
        if (!StringUtils.hasText(token)) {
            return false;
        }

        try {
            // 1. 验证JWT Token格式和签名
            if (!jwtUtils.validateToken(token)) {
                return false;
            }

            // 2. 检查内存中是否存在
            Object userIdObj = getFromTokenStore(TOKEN_PREFIX + token);
            if (userIdObj == null) {
                return false;
            }

            // 3. 检查用户状态
            Long userId = (Long) userIdObj;
            SysUser user = userService.getById(userId);
            return user != null && user.getStatus() == 1;

        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public Long getUserIdFromToken(String token) {
        if (!StringUtils.hasText(token)) {
            return null;
        }

        try {
            // 先从内存获取
            Object userIdObj = getFromTokenStore(TOKEN_PREFIX + token);
            if (userIdObj != null) {
                return (Long) userIdObj;
            }

            // 如果Redis中没有，尝试从JWT中解析
            Map<String, Object> claims = jwtUtils.getClaimsFromToken(token);
            if (claims != null && claims.containsKey("userId")) {
                return Long.valueOf(claims.get("userId").toString());
            }

            return null;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public boolean hasPermission(Long userId, String permission) {
        if (userId == null || !StringUtils.hasText(permission)) {
            return false;
        }

        List<String> userPermissions = getUserPermissions(userId);
        return userPermissions.contains(permission);
    }

    /**
     * 获取用户权限列表
     */
    private List<String> getUserPermissions(Long userId) {
        // 先从缓存获取
        String cacheKey = USER_PERMISSIONS_PREFIX + userId;
        @SuppressWarnings("unchecked")
        List<String> permissions = (List<String>) getFromTokenStore(cacheKey);

        if (permissions == null) {
            // 从数据库查询（这里简化处理，实际应该查询用户角色权限）
            permissions = loadUserPermissionsFromDatabase(userId);

            // 缓存30分钟
            long currentTime = System.currentTimeMillis();
            tokenStore.put(cacheKey, permissions);
            tokenExpireTime.put(cacheKey, currentTime + 30 * 60 * 1000L);
        }
        
        return permissions != null ? permissions : new ArrayList<>();
    }

    /**
     * 获取用户角色列表
     */
    private List<String> getUserRoles(Long userId) {
        SysUser user = userService.getById(userId);
        List<String> roles = new ArrayList<>();
        
        if (user != null && user.getRoleId() != null) {
            // 这里简化处理，实际应该从角色表查询
            switch (user.getRoleId().intValue()) {
                case 1:
                    roles.add("SUPER_ADMIN");
                    break;
                case 2:
                    roles.add("ADMIN");
                    break;
                case 3:
                    roles.add("LAWYER");
                    break;
                case 4:
                    roles.add("ASSISTANT");
                    break;
                case 5:
                    roles.add("CLIENT");
                    break;
                default:
                    roles.add("USER");
                    break;
            }
        }
        
        return roles;
    }

    /**
     * 从数据库加载用户权限
     */
    private List<String> loadUserPermissionsFromDatabase(Long userId) {
        // 这里简化处理，实际应该查询用户角色权限表
        SysUser user = userService.getById(userId);
        List<String> permissions = new ArrayList<>();
        
        if (user != null && user.getRoleId() != null) {
            switch (user.getRoleId().intValue()) {
                case 1: // 超级管理员
                    permissions.add("*:*:*"); // 所有权限
                    break;
                case 2: // 管理员
                    permissions.add("system:user:*");
                    permissions.add("business:*:*");
                    break;
                case 3: // 律师
                    permissions.add("business:client:*");
                    permissions.add("business:case:*");
                    permissions.add("business:contract:*");
                    permissions.add("business:document:*");
                    permissions.add("business:finance:view");
                    break;
                case 4: // 助理
                    permissions.add("business:client:view");
                    permissions.add("business:case:view");
                    permissions.add("business:contract:view");
                    permissions.add("business:document:*");
                    break;
                case 5: // 客户
                    permissions.add("business:client:view:own");
                    permissions.add("business:case:view:own");
                    permissions.add("business:contract:view:own");
                    break;
            }
        }
        
        return permissions;
    }
}
